from google.appengine.ext import db

import logging

from Location import *
from Calendar import *
from Activity import *
from CheckIn import *
from util import *
from Trip import *

class Person(db.Model):
    firstName = db.StringProperty()
    lastName = db.StringProperty()
    email = db.StringProperty()
    password = db.StringProperty()
    homeLocation = db.ReferenceProperty(Location, collection_name="homeLocation_set")
    workLocation = db.ReferenceProperty(Location, collection_name="workLocation_set")
    lastQuestionsDate = db.DateTimeProperty()
    
    def save(self):
        self.put()
        self.id = self.key().id()

    def setActivity(self, date):
        cal = self.getCalendar()
        self.currentActivity = cal.getActivityAtTime(date)
        if self.currentActivity == None:
            self.currentActivity = Activity()
            self.currentActivity.name = "tuller rundt"
            return

    def setLocation(self, date):
        cal = self.getCalendar()
        #if cal.getEntriesToday() == []:
        self.createCalendarEntries(date)
        #print "p.setLocation ", self.homeLocation, self.workLocation
        calEntry = cal.getEntryAtTime(date)
        if calEntry:
            if calEntry.location:
                self.currentLocation = calEntry.location
                return
            if calEntry.activity.type == "travel":
                l1, l2 = cal.getPrevAndNextLocation(calEntry)
                if l1 == None and l2 == None:
                    return self.homeLocation
                if l1 == None:
                    l1 = self.homeLocation
                if l2 == None:
                    l2 = self.homeLocation
                directions = Directions(l1, l2)
                #print "setLoc between ", l1, l2
                dt = date - calEntry.date
                # Scale dt to time found in directions
                travelTime = self.travelTime(l1, l2)
                factor = travelTime[0] / travelTime[1]
                print factor
                dt = timedelta(seconds = factor*dt.seconds)
                position = PositionAlongDirections(directions, dt)
                location = Location()
                location.lat = position[1]
                location.lng = position[0]
                #print location.lat, location.lng
                self.currentLocation = location
                #print dt
                #fraction = dt.seconds / (3600.0 * calEntry.duration)
                #self.currentLocation = interpolateLocation(l1, l2, fraction)
                return
        # If there is nothing in the calendar, then assume we are home
        if self.homeLocation:
            self.currentLocation = self.homeLocation
            #print self.currentLocation.zipCode
            return
        self.currentLocation = LoadLocationDefault()

    def createCalendarEntries(self, date):
        if not self.homeLocation:
            return
        cal = self.getCalendar()
        cal.deleteAllEntriesOnDay(date)
        a = LoadOrCreateActivity(name="sover")
        date = localDatetime(date.year, date.month, date.day, 0, 0)
        cal.addEntry(a, date, 7.0, self.homeLocation)
        date = localDatetime(date.year, date.month, date.day, 23, 0)
        cal.addEntry(a, date, 8.0, self.homeLocation)
        if not self.workLocation:
            return
        a = LoadOrCreateActivity(name="arbejder")
        date = localDatetime(date.year, date.month, date.day, 9, 0)
        cal.addEntry(a, date, 8.0, self.workLocation)
        travelHours = self.travelTime(self.homeLocation, self.workLocation)[1]
        tdTravel = timedelta(hours=travelHours)
        a = LoadOrCreateActivity(name="er p&aring; vej", type="travel")
        date = localDatetime(date.year, date.month, date.day, 9, 0)
        date = date - tdTravel
        cal.addEntry(a, date, travelHours, None)
        date = localDatetime(date.year, date.month, date.day, 17, 0)
        cal.addEntry(a, date, travelHours, None)

    def getCalendar(self):
        return Calendar(self.id)

    def travelTime(self, l1, l2):
        trip = Trip_getOrCreate(self.id, l1, l2)
        return (trip.duration, trip.userDuration)

    def getCheckInsToday(self):
        now = TimeNow()
        d1 = localDatetime(now.year, now.month, now.day, 0, 0)
        d2 = d1 + timedelta(hours=24)
        return self.getCheckInsInInterval(d1, d2)

    def addTZInfo(self, entries):
        for entry in entries:
            if entry.date.tzinfo == None:
                entry.date = addUTC(entry.date)
            entry.date = fromUTC(entry.date)

    def getCheckInsInInterval(self, date1, date2, maxEntries=200):
        checkInQ = db.GqlQuery("SELECT * FROM CheckIn WHERE userId=:1 AND date >= :2 AND date < :3 ORDER BY date ASC", self.id, date1, date2)
        checkIns = checkInQ.fetch(maxEntries)
        self.addTZInfo(checkIns)
        return checkIns

    def addCheckIn(self, activity, date, location):
        checkIn = CheckIn()
        checkIn.userId = self.id
        checkIn.date = date
        checkIn.activity = activity
        checkIn.location = location
        checkIn.put()

    def getActivities(self, location):
        return LoadAllActivities(10)

def LoadPerson(email):
    personQ = db.GqlQuery("SELECT * FROM Person WHERE email=:1", email)
    person = personQ.get()
    if not person:
        return None
    person.id = person.key().id()
    return person

def LoadPersonFromId(id):
    key = db.Key.from_path('Person', long(id))
    person = db.get(key)
    if not person:
        return None
    person.id = person.key().id()
    return person

